/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2002-2006 * Sleepycat Software. All rights reserved. * * $Id: Key.java,v 1.1 2006/05/06 09:00:20 ckaestne Exp $ */ package com.sleepycat.je.tree; import java.util.Comparator; import com.sleepycat.je.DatabaseEntry; /** * Key represents a JE B-Tree Key. Keys are immutable. Within JE, keys are * usually represented as byte arrays rather than as Key instances in order to * reduce the in-memory footprint. The static methods of this class are used to * operate on the byte arrays. * * One exception is when keys are held within a collection. In that case, Key * objects are instantiated so that keys are hashed and compared by value. */ public final class Key implements Comparable { public static boolean DUMP_BINARY = true; /* Not declared final since unit tests use it. */ public static boolean DUMP_INT_BINDING = false; public static final byte[] EMPTY_KEY = new byte[0]; private byte[] key; /** * Construct a new key from a byte array. */ public Key(byte[] key) { if (key == null) { this.key = null; } else { this.key = new byte[key.length]; System.arraycopy(key, 0, this.key, 0, key.length); } } public static byte[] makeKey(DatabaseEntry dbt) { byte[] entryKey = dbt.getData(); if (entryKey == null) { return EMPTY_KEY; } else { byte[] newKey = new byte[dbt.getSize()]; System.arraycopy(entryKey, dbt.getOffset(), newKey, 0, dbt.getSize()); return newKey; } } /** * Get the byte array for the key. */ public byte[] getKey() { return key; } /** * Compare two keys. Standard compareTo function and returns. * * Note that any configured user comparison function is not used, and * therefore this method should not be used for comparison of keys during * Btree operations. */ public int compareTo(Object o) { if (o == null) { throw new NullPointerException(); } Key argKey = (Key) o; return compareUnsignedBytes(this.key, argKey.key); } /** * Support Set of Key in BINReference. */ public boolean equals(Object o) { return (o instanceof Key) && (compareTo(o) == 0); } /** * Support HashSet of Key in BINReference. */ public int hashCode() { int code = 0; for (int i = 0; i < key.length; i += 1) { code += key[i]; } return code; } /** * Compare keys with an optional comparator. */ public static int compareKeys(byte[] key1, byte[] key2, Comparator comparator) { if (comparator != null) { return comparator.compare(key1, key2); } else { return compareUnsignedBytes(key1, key2); } } /** * Compare using a default unsigned byte comparison. */ private static int compareUnsignedBytes(byte[] key1, byte[] key2) { int a1Len = key1.length; int a2Len = key2.length; int limit = Math.min(a1Len, a2Len); for (int i = 0; i < limit; i++) { byte b1 = key1[i]; byte b2 = key2[i]; if (b1 == b2) { continue; } else { /* Remember, bytes are signed, so convert to shorts so that we effectively do an unsigned byte comparison. */ return (b1 & 0xff) - (b2 & 0xff); } } return (a1Len - a2Len); } public static String dumpString(byte[] key, int nspaces){ StringBuffer sb = new StringBuffer(); sb.append(TreeUtils.indent(nspaces)); sb.append("<key v=\""); /** uncomment for hex formatting for (int i = 0 ; i < key.length; i++) { sb.append(Integer.toHexString(key[i] & 0xFF)).append(" "); } **/ if (DUMP_BINARY) { if (key == null) { sb.append("<null>"); } else { sb.append(TreeUtils.dumpByteArray(key)); } } else if (DUMP_INT_BINDING) { if (key == null) { sb.append("<null>"); } else { DatabaseEntry e = new DatabaseEntry(key); // sb.append(IntegerBinding.entryToInt(e)); } } else { sb.append(key == null ? "" : new String(key)); } sb.append("\"/>"); return sb.toString(); } /** * Print the string w/out XML format. */ public static String getNoFormatString(byte[] key) { return "key=" + dumpString(key, 0); } }